package com.hup.timer.service.gesture;

import com.hup.utils.commons.hardware.MouseUtil;

import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

/**
 * 鼠标事件分发器
 * @author hugan
 * @date 2020/4/6
 */
public class TimerWindowGesture implements MouseListener, MouseMotionListener {

    public static TimerWindowGesture bind(GestureCallback callback) {
        TimerWindowGesture gesture = new TimerWindowGesture(callback);
        Window window = callback.getWindow();
        window.addMouseListener(gesture);
        window.addMouseMotionListener(gesture);
        return gesture;
    }

    private GestureCallback callback;
    private final MoveFrameListener moveFrameListener;
    private final SetAlphaListener setAlphaListener;
    private final SetSizeListener setSizeListener;
    private final SimpleActionListener simpleActionListener;

    private boolean isMoving;
    private boolean changingAlpha;
    private boolean changingSize;

    private TimerWindowGesture(GestureCallback callback) {
        this.callback = callback;
        moveFrameListener = new MoveFrameListener(callback);
        setAlphaListener = new SetAlphaListener(callback);
        setSizeListener = new SetSizeListener(callback);
        simpleActionListener = new SimpleActionListener(callback);
    }

    @Override
    public void mousePressed(MouseEvent e) {
        simpleActionListener.mousePressed(e);

        if (MouseUtil.isLeftButton(e)) {
            boolean controlDown = e.isControlDown();
            boolean shiftDown = e.isShiftDown();
            if (controlDown && shiftDown) return;//同时按下,不激活操作

            if (controlDown) {
                changingAlpha = true;
                setAlphaListener.mousePressed(e);
            } else if (shiftDown) {
                changingSize = true;
                setSizeListener.mousePressed(e);
            } else {
                //只有移动才需要限制点击次数
                if (callback.actBy2Click() && e.getClickCount() == 1) return;
                isMoving = true;
                moveFrameListener.mousePressed(e);
            }
        }
    }

    @Override
    public void mouseDragged(MouseEvent e) {
        if (isMoving) {
            moveFrameListener.mouseDragged(e);
        } else if (changingAlpha) {
            setAlphaListener.mouseDragged(e);
        } else if(changingSize){
            setSizeListener.mouseDragged(e);
        }
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        if (isMoving) {
            isMoving = false;
            moveFrameListener.mouseReleased(e);
        } else if (changingAlpha) {
            changingAlpha = false;
            setAlphaListener.mouseReleased(e);
        } else if(changingSize){
            changingSize = false;
            setSizeListener.mouseReleased(e);
        } else {
            if (callback.actBy2Click() && e.getClickCount() == 1) return;
            simpleActionListener.mouseReleased(e);
        }
    }

    private boolean isComplexTasking() {
        return isMoving || changingAlpha || changingSize;
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        simpleActionListener.mouseClicked(e);
    }

    @Override
    public void mouseEntered(MouseEvent e) {
        if (!isComplexTasking()) {
            simpleActionListener.mouseEntered(e);
        }
    }

    @Override
    public void mouseExited(MouseEvent e) {
        if (!isComplexTasking()) {
            simpleActionListener.mouseExited(e);
        }
    }

    @Override
    public void mouseMoved(MouseEvent e) {

    }

    public interface GestureCallback {

        Window getWindow();

        boolean disableWindowMenu();

        boolean actBy2Click();

        void afterMoved();

        float getAlpha();

        void afterChangedAlpha(float alpha);

        void onSizeLimit();

        void afterChangedSize(int fontSize);

        void moveToBootLoc();

        boolean isShowingMenu();

        void showMenu(MouseEvent e);

        boolean isDisableWindowMenu();

        void switchDisableWindowMenu();
    }

}
